package com.foodapp.back.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.foodapp.back.dto.OrderCreateDTO;
import com.foodapp.back.dto.OrderItemDTO;
import com.foodapp.back.entity.Dish;
import com.foodapp.back.entity.Order;
import com.foodapp.back.entity.OrderItem;
import com.foodapp.back.entity.Restaurant;
import com.foodapp.back.entity.User;
import com.foodapp.back.exception.ApiException;
import com.foodapp.back.mapper.OrderMapper;
import com.foodapp.back.service.DishService;
import com.foodapp.back.service.OrderItemService;
import com.foodapp.back.service.OrderService;
import com.foodapp.back.service.RestaurantService;
import com.foodapp.back.service.UserService;
import com.foodapp.back.vo.OrderItemVO;
import com.foodapp.back.vo.OrderVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 订单服务实现类
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Resource
    private UserService userService;

    @Resource
    private RestaurantService restaurantService;

    @Resource
    private DishService dishService;

    @Resource
    private OrderItemService orderItemService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createOrder(Long userId, OrderCreateDTO orderCreateDTO) {
        // 校验用户是否存在
        User user = userService.getById(userId);
        if (user == null) {
            throw new ApiException("用户不存在");
        }

        // 校验餐厅是否存在
        Restaurant restaurant = restaurantService.getById(orderCreateDTO.getRestaurantId());
        if (restaurant == null) {
            throw new ApiException("餐厅不存在");
        }

        // 校验餐厅是否营业
        if (restaurant.getStatus() != 1) {
            throw new ApiException("餐厅已打烊");
        }

        // 计算订单金额
        BigDecimal totalAmount = BigDecimal.ZERO;
        List<OrderItem> orderItems = new ArrayList<>();

        for (OrderItemDTO itemDTO : orderCreateDTO.getOrderItems()) {
            // 获取菜品信息
            Dish dish = dishService.getById(itemDTO.getDishId());
            if (dish == null) {
                throw new ApiException("菜品不存在");
            }

            // 校验菜品是否属于该餐厅
            if (!dish.getRestaurantId().equals(orderCreateDTO.getRestaurantId())) {
                throw new ApiException("菜品不属于该餐厅");
            }

            // 校验菜品是否上架
            if (dish.getStatus() != 1) {
                throw new ApiException("菜品已下架");
            }

            // 校验库存是否足够
            if (dish.getStock() < itemDTO.getQuantity()) {
                throw new ApiException("菜品库存不足");
            }

            // 计算订单项金额
            BigDecimal itemAmount = dish.getPrice().multiply(new BigDecimal(itemDTO.getQuantity()));
            totalAmount = totalAmount.add(itemAmount);

            // 创建订单项
            OrderItem orderItem = new OrderItem();
            orderItem.setDishId(dish.getId());
            orderItem.setDishName(dish.getName());
            orderItem.setDishImage(dish.getImage());
            orderItem.setDishPrice(dish.getPrice());
            orderItem.setQuantity(itemDTO.getQuantity());
            orderItem.setTotalAmount(itemAmount);

            orderItems.add(orderItem);

            // 更新库存和销量
            dish.setStock(dish.getStock() - itemDTO.getQuantity());
            dish.setSales(dish.getSales() + itemDTO.getQuantity());
            dishService.updateById(dish);
        }

        // 校验起送价
        if (totalAmount.compareTo(restaurant.getMinOrderAmount()) < 0) {
            throw new ApiException("未达到起送价￥" + restaurant.getMinOrderAmount());
        }

        // 生成订单号
        String orderNo = generateOrderNo(userId);

        // 创建订单
        Order order = new Order();
        order.setOrderNo(orderNo);
        order.setUserId(userId);
        order.setRestaurantId(restaurant.getId());
        order.setRestaurantName(restaurant.getName());
        order.setReceiverName(orderCreateDTO.getReceiverName());
        order.setReceiverPhone(orderCreateDTO.getReceiverPhone());
        order.setReceiverAddress(orderCreateDTO.getReceiverAddress());
        order.setTotalAmount(totalAmount);
        order.setDeliveryFee(restaurant.getDeliveryFee());
        order.setPayAmount(totalAmount.add(restaurant.getDeliveryFee()));
        order.setPayType(orderCreateDTO.getPayType());
        order.setStatus(0); // 待支付
        order.setRemark(orderCreateDTO.getRemark());
        
        // 保存订单
        save(order);
        
        // 更新订单项中的订单ID和订单号
        for (OrderItem item : orderItems) {
            item.setOrderId(order.getId());
            item.setOrderNo(orderNo);
        }
        
        // 批量保存订单项
        orderItemService.saveBatch(orderItems);
        
        // 更新餐厅月销量
        restaurant.setMonthlySales(restaurant.getMonthlySales() + 1);
        restaurantService.updateById(restaurant);
        
        return order.getId();
    }

    @Override
    public Page<OrderVO> getUserOrderList(Long userId, Integer page, Integer size, Integer status) {
        Page<Order> pageParam = new Page<>(page, size);
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        
        // 查询条件
        wrapper.eq(Order::getUserId, userId);
        
        if (status != null) {
            wrapper.eq(Order::getStatus, status);
        }
        
        // 按创建时间降序排序
        wrapper.orderByDesc(Order::getCreateTime);
        
        // 查询分页数据
        Page<Order> orderPage = page(pageParam, wrapper);
        
        // 转换为VO
        Page<OrderVO> result = new Page<>();
        BeanUtils.copyProperties(orderPage, result, "records");
        
        List<OrderVO> orderVOList = orderPage.getRecords().stream().map(order -> {
            OrderVO orderVO = new OrderVO();
            BeanUtils.copyProperties(order, orderVO);
            
            // 获取订单项
            List<OrderItemVO> orderItemVOList = orderItemService.getOrderItemsByOrderId(order.getId());
            orderVO.setOrderItems(orderItemVOList);
            
            return orderVO;
        }).collect(Collectors.toList());
        
        result.setRecords(orderVOList);
        
        return result;
    }

    @Override
    public OrderVO getOrderDetail(Long id) {
        Order order = getById(id);
        if (order == null) {
            throw new ApiException("订单不存在");
        }
        
        OrderVO orderVO = new OrderVO();
        BeanUtils.copyProperties(order, orderVO);
        
        // 获取订单项
        List<OrderItemVO> orderItemVOList = orderItemService.getOrderItemsByOrderId(order.getId());
        orderVO.setOrderItems(orderItemVOList);
        
        // 获取用户信息
        User user = userService.getById(order.getUserId());
        if (user != null) {
            orderVO.setUsername(user.getUsername());
        }
        
        return orderVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelOrder(Long userId, Long orderId) {
        // 获取订单
        Order order = getById(orderId);
        if (order == null) {
            throw new ApiException("订单不存在");
        }
        
        // 校验订单所属
        if (!order.getUserId().equals(userId)) {
            throw new ApiException("无权操作此订单");
        }
        
        // 校验订单状态
        if (order.getStatus() != 0) {
            throw new ApiException("只有待支付订单可以取消");
        }
        
        // 更新订单状态
        order.setStatus(4); // 已取消
        boolean result = updateById(order);
        
        if (result) {
            // 恢复库存和销量
            List<OrderItemVO> orderItems = orderItemService.getOrderItemsByOrderId(orderId);
            for (OrderItemVO item : orderItems) {
                Dish dish = dishService.getById(item.getDishId());
                if (dish != null) {
                    dish.setStock(dish.getStock() + item.getQuantity());
                    dish.setSales(dish.getSales() - item.getQuantity());
                    dishService.updateById(dish);
                }
            }
            
            // 更新餐厅月销量
            Restaurant restaurant = restaurantService.getById(order.getRestaurantId());
            if (restaurant != null) {
                restaurant.setMonthlySales(restaurant.getMonthlySales() - 1);
                restaurantService.updateById(restaurant);
            }
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean payOrder(Long userId, Long orderId) {
        // 获取订单
        Order order = getById(orderId);
        if (order == null) {
            throw new ApiException("订单不存在");
        }
        
        // 校验订单所属
        if (!order.getUserId().equals(userId)) {
            throw new ApiException("无权操作此订单");
        }
        
        // 校验订单状态
        if (order.getStatus() != 0) {
            throw new ApiException("只有待支付订单可以支付");
        }
        
        // 更新订单状态
        order.setStatus(1); // 已支付
        order.setPayTime(LocalDateTime.now());
        
        return updateById(order);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateOrderStatus(Long orderId, Integer status) {
        // 获取订单
        Order order = getById(orderId);
        if (order == null) {
            throw new ApiException("订单不存在");
        }
        
        // 校验状态变更合法性
        validateStatusChange(order.getStatus(), status);
        
        // 更新订单状态
        order.setStatus(status);
        
        // 配送中状态记录配送时间
        if (status == 2) {
            order.setDeliveryTime(LocalDateTime.now());
        }
        
        return updateById(order);
    }

    @Override
    public Page<OrderVO> getAdminOrderList(Integer page, Integer size, Long restaurantId, Integer status, String orderNo) {
        Page<Order> pageParam = new Page<>(page, size);
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        
        // 查询条件
        if (restaurantId != null) {
            wrapper.eq(Order::getRestaurantId, restaurantId);
        }
        
        if (status != null) {
            wrapper.eq(Order::getStatus, status);
        }
        
        if (StringUtils.isNotBlank(orderNo)) {
            wrapper.like(Order::getOrderNo, orderNo);
        }
        
        // 按创建时间降序排序
        wrapper.orderByDesc(Order::getCreateTime);
        
        // 查询分页数据
        Page<Order> orderPage = page(pageParam, wrapper);
        
        // 转换为VO
        Page<OrderVO> result = new Page<>();
        BeanUtils.copyProperties(orderPage, result, "records");
        
        List<OrderVO> orderVOList = orderPage.getRecords().stream().map(order -> {
            OrderVO orderVO = new OrderVO();
            BeanUtils.copyProperties(order, orderVO);
            
            // 获取订单项
            List<OrderItemVO> orderItemVOList = orderItemService.getOrderItemsByOrderId(order.getId());
            orderVO.setOrderItems(orderItemVOList);
            
            // 获取用户信息
            User user = userService.getById(order.getUserId());
            if (user != null) {
                orderVO.setUsername(user.getUsername());
            }
            
            return orderVO;
        }).collect(Collectors.toList());
        
        result.setRecords(orderVOList);
        
        return result;
    }
    
    /**
     * 生成订单号
     */
    private String generateOrderNo(Long userId) {
        // 时间戳 + 用户ID + 随机数
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String random = String.valueOf((int) (Math.random() * 9000 + 1000));
        return timestamp + userId % 100 + random;
    }
    
    /**
     * 校验订单状态变更合法性
     */
    private void validateStatusChange(Integer currentStatus, Integer targetStatus) {
        // 合法的状态变更
        // 0(待支付) -> 1(已支付)/4(已取消)
        // 1(已支付) -> 2(配送中)/4(已取消)
        // 2(配送中) -> 3(已完成)/4(已取消)
        
        boolean isValid = false;
        
        switch (currentStatus) {
            case 0:
                isValid = targetStatus == 1 || targetStatus == 4;
                break;
            case 1:
                isValid = targetStatus == 2 || targetStatus == 4;
                break;
            case 2:
                isValid = targetStatus == 3 || targetStatus == 4;
                break;
            default:
                break;
        }
        
        if (!isValid) {
            throw new ApiException("订单状态变更不合法");
        }
    }
}
